package com.qf.index;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DeptTopJournal {

    /**
     * 各科室的top期刊，先从期刊关联表（jourMergeTable）中获取中科院一区的TOP医学期刊，共计398本，再按中科院的科目使用通义，获取复旦或STEM的科室（方法Dept.tongYiDeptName），最后写入字典中（filePath）。
     * fuDan_呼吸科_51785_Eur Respir J
     * STEM_呼吸病学_51785_Eur Respir J
     * 数据格式如上，共分为4个部分，分别是复旦或STEM的科室、科室、JID、期刊，使用时需要注意，同一个科室下可能有多本期刊。
     * 贾新志 2025.02.15
     */

    public static void main(String[] args) throws SQLException {
        String newDataName = "scholar_25_01.";
        String zkyTopJourMedTable = "scholar_25_01.zky_top_jour_med";
        String jourMergeTable = newDataName + "basic_jour_merge";

        insertZkyTopJourMedTable(jourMergeTable, "id", "zky_category`,`zky_subcategory`,`nc_nlm_title_abbreviation", zkyTopJourMedTable);

        String user = "Bearer sk-c65ee8baf0c440238e51f74495107da3";
        for (int i = 0; i < 10; i++) {
            Dept.tongYiDeptName(zkyTopJourMedTable, "id", "info`,`fudan`,`stem`,`you_dao", user, 0, 100);
        }

        String filePath = "F:\\WorkSpaces\\Data\\src\\main\\resources\\dict\\dept_top_journal_zky.txt";
        FileUtil.appendUtf8String("2025.02.15 各科室的top期刊，基于中科院" + System.lineSeparator(), filePath);
        saveDeptTopJournal(zkyTopJourMedTable, "id", "journal`,`jid`,`fudan`,`stem", filePath);
    }

    public static void saveDeptTopJournal(String zkyTopJourMedTable, String autoId, String field, String filePath) throws SQLException {
        int onePageNum = 1000;
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + zkyTopJourMedTable);
        Set<String> stemSet = uSet.getStemSet();
        Set<String> fuDanSet = uSet.getFuDanSet();
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + zkyTopJourMedTable).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            for (Integer startId : tableList) {
                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + zkyTopJourMedTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
                for (Entity entry : tableData) {
                    String journal = Utils.getStrField(entry, "journal");
                    int jid = Utils.getIntField(entry, "jid");
                    if (jid > 0 && journal.length() > 2) {
                        saveFile(entry.getStr("fudan"), "fuDan", filePath, jid, journal, fuDanSet);
                        saveFile(entry.getStr("stem"), "STEM", filePath, jid, journal, stemSet);
                    }
                }
            }
        }
    }

    public static void saveFile(String fuDanOrStem, String type, String filePath, int jid, String journal, Set<String> stemOrFuDanSet) {
        if (null != fuDanOrStem && fuDanOrStem.contains("\"}]")) {
            List<En.UnitInfo> unitInfoList = JSONObject.parseArray(fuDanOrStem, En.UnitInfo.class);
            for (En.UnitInfo unitInfo : unitInfoList) {
                String dept = unitInfo.getUnit().trim();
                dept = dept.startsWith("[") && dept.endsWith("]") ? dept.substring(1, dept.length() - 1).trim() : dept;
                System.out.println("dept: " + dept);
                if (stemOrFuDanSet.contains(dept)) {
                    FileUtil.appendUtf8String(type + "_" + dept + "_" + jid + "_" + journal + System.lineSeparator(), filePath);
                }
            }
        }
    }

    public static void putStrEnStrInt(String type, String name, Map<String, Map<String, Integer>> strStrIntMap) {
        if (null != type && type.length() > 1 && null != name && name.length() > 1 && !Utils.isContainChinese(name)) {
            strStrIntMap.compute(type, (k, v) -> {
                if (v == null) {
                    v = new ConcurrentHashMap<>();
                }
                v.compute(name, (key, value) -> value != null ? (value + 1) : 1);
                return v;
            });
        }
    }

    public static void insertZkyTopJourMedTable(String jourMergeTable, String autoId, String field, String zkyTopJourMedTable) throws SQLException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int onePageNum = 1000;
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + jourMergeTable);
        Db.use().execute("truncate table " + zkyTopJourMedTable);
        Set<String> nameSet = new HashSet<>();
        Map<Integer, String> jidAndJournalMap = new HashMap<>();
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + jourMergeTable).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            for (Integer startId : tableList) {
                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + jourMergeTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
                System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + jourMergeTable + Utils.printMemoryStr() + "\033[0m");
                for (Entity entry : tableData) {
                    String zkyCategory = entry.getStr("zky_category");
                    Integer jid = entry.getInt(autoId);
                    String journal = entry.getStr("nc_nlm_title_abbreviation");
                    if (null != zkyCategory && zkyCategory.contains("[{\"fq\":\"1\",\"type\":\"大类\",\"top\":\"是\",\"name\":\"医学\"}]") && null != jid && jid > 0 && null != journal && journal.length() > 2) {
                        String zkySubcategory = entry.getStr("zky_subcategory");
                        jidAndJournalMap.put(jid, journal);
                        List<ZkyCategory> zkyList = null != zkySubcategory && zkySubcategory.contains("\"}]") ? JSONObject.parseArray(zkySubcategory, ZkyCategory.class) : new ArrayList<>();
                        for (ZkyCategory category : zkyList) {
                            String name = category.getName();
                            Matcher matcher = Pattern.compile("[\\u4e00-\\u9fa5：]+").matcher(name);
                            while (matcher.find()) {
                                String group = matcher.group().trim();
                                if (group.length() > 1) {
                                    nameSet.add(group + "_" + jid);
                                }
                            }
                        }
                    }
                }
            }
        }

        for (String names : nameSet) {
            String[] split = names.split("_");
            if (split.length == 2 && NumberUtil.isInteger(split[1])) {
                int jid = Integer.parseInt(split[1]);
                try {
                    Db.use().insert(Entity.create(zkyTopJourMedTable).set("info", split[0]).set("jid", jid).set("you_dao", "you_dao").set("journal", jidAndJournalMap.getOrDefault(jid, "")));
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void mapSortValueIntLen2(Map<String, Map<String, Integer>> fuDanDeptInfoSumMap, String type, String stemFuDanDeptSumTable) {
        for (Map.Entry<String, Map<String, Integer>> entry : fuDanDeptInfoSumMap.entrySet()) {
            Map<String, Integer> stringIntegerMap = mapSortValueIntLen(entry.getValue(), 15);
            for (Map.Entry<String, Integer> map : stringIntegerMap.entrySet()) {
                try {
                    Db.use().insert(Entity.create(stemFuDanDeptSumTable).set("stem_fudan", type).set("dept_name", entry.getKey()).set("dept", map.getKey()).set("sum", map.getValue()));
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    public static Map<String, Integer> mapSortValueIntLen(Map<String, Integer> mapName, Integer len) {
        Map<String, Integer> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue()
                        .reversed()).limit(len).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    @Data
    public static class ZkyCategory {
        private String fq = "";
        private String type = "";
        private String top = "";
        private String name = "";
    }


}
